package com.xique.park.controller.mini;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.spatial4j.core.io.GeohashUtils;
import com.xique.common.core.utils.OrikaUtil;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.utils.StringUtils;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.common.core.web.domain.PageResult;
import com.xique.park.bean.domain.ParkConfig;
import com.xique.park.bean.domain.ParkInfo;
import com.xique.park.bean.request.mini.OrderRequest;
import com.xique.park.bean.request.mini.SaveUserPlateRequest;
import com.xique.park.bean.request.mini.SelectNearByParkRequest;
import com.xique.park.bean.vo.mini.MiniParkInfo;
import com.xique.park.bean.vo.web.parkingOrder.ParkingOrderVo;
import com.xique.park.service.biz.service.IMiniProgramBizService;
import com.xique.park.service.service.IParkConfigService;
import com.xique.park.service.service.IParkInfoService;
import com.xique.park.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Point;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: caogq
 * @Date: 2022/8/3 11:58
 * @Description:
 */
@RestController
@RequestMapping("mini")
@Slf4j
public class MiniProgramHomeController {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IParkInfoService parkInfoService;

    @Autowired
    private IMiniProgramBizService miniProgramBizService;

    @Autowired
    private IParkConfigService parkConfigService;

    @GetMapping("/getParkInfo")
    public AjaxResult getParkInfo(Long parkId) {
        //获取车场基本信息
        ParkInfo parkInfo = parkInfoService.getById(parkId);
        MiniParkInfo miniParkInfo = OrikaUtil.convert(parkInfo, MiniParkInfo.class);
        ParkConfig parkConfig = new ParkConfig();
        parkConfig.setParkId(parkId);
        Integer payStayTime = 15;
        List<ParkConfig> configList = parkConfigService.selectParkConfigList(parkConfig);
        if (!CollUtil.isEmpty(configList)){
            String config = configList.get(0).getConfig();
            if (StrUtil.isNotEmpty(config)){
                JSONObject configObj = JSON.parseObject(config);
                payStayTime =  configObj.getInteger("payStayTime");
            }
            miniParkInfo.setServicePhone(configList.get(0).getServicePhone());
        }

        miniParkInfo.setPayStayTime(payStayTime);
        return AjaxResult.success(miniParkInfo);
    }

    @GetMapping("/saveParkInfo")
    public AjaxResult saveParkInfo(Long parkId) {
        //redis-geo 执行此代码，存储指定车场定位数据
        ParkInfo parkInfo = parkInfoService.getById(parkId);
        redisUtil.saveGeoParkInfo(parkInfo);
        return AjaxResult.success();
    }

    @GetMapping("/saveAllParkInfo")
    public AjaxResult saveAllParkInfo() {
        ///redis-geo 执行此代码，批量存储车场定位数据
        List<ParkInfo> parkInfos = parkInfoService.selectAll();
        Map<Object, Point> parkInfoMap = new HashMap<>();
        for (ParkInfo parkInfo : parkInfos) {
            if (!StrUtil.equals("Y", parkInfo.getIsOpenPark())) {
                break;
            }
            if (parkInfo.getPositionX() != null && parkInfo.getPositionY() != null) {
                if (parkInfo.getPositionY() > 90) {
                    parkInfoMap.put(parkInfo.getId(), new Point(parkInfo.getPositionY(), parkInfo.getPositionX()));
                } else {
                    parkInfoMap.put(parkInfo.getId(), new Point(parkInfo.getPositionX(), parkInfo.getPositionY()));
                }
            }
        }
        redisUtil.saveBatchGeoParkInfo(parkInfoMap);
        return AjaxResult.success();
    }

    @GetMapping("/getNearByParkInfo")
    public AjaxResult getNearByParkInfo(@Validated SelectNearByParkRequest request) {
        AjaxResult ajaxResult = miniProgramBizService.getNearByParkInfoRedis(request);
        return AjaxResult.success(ajaxResult);
    }

    /***
     * 生成车场定GEOHASH编码
     * @return
     */
    @GetMapping("/updateParkInfo")
    public boolean add(Long parkId, String isAll) {
        //恢复数据用
        if ("Y".equals(isAll)) {
            List<ParkInfo> parkInfos = parkInfoService.selectAll();
            for (ParkInfo parkInfo : parkInfos) {
                if (parkInfo.getPositionX() != null && parkInfo.getPositionY() != null && parkInfo.getPositionY() < 85.05112878) {
                    String geoHashCode = GeohashUtils.encodeLatLon(parkInfo.getPositionY(), parkInfo.getPositionX());
                    parkInfo.setGeoCode(geoHashCode);
                }
            }
            return parkInfoService.updateBatchById(parkInfos);
        } else {
            ParkInfo parkInfo = parkInfoService.getById(parkId);
            //默认精度12位
            if (parkInfo.getPositionX() != null && parkInfo.getPositionY() != null && parkInfo.getPositionY() < 85.05112878) {
                String geoHashCode = GeohashUtils.encodeLatLon(parkInfo.getPositionY(), parkInfo.getPositionX());
                parkInfo.setGeoCode(geoHashCode);
                return parkInfoService.updateById(parkInfo);
            }
            return false;
        }
    }


    /**
     * 获取附近指定范围的人
     * <p>
     * len
     * 1 | 5,009.4km | 4,992.6km
     * 2 |1,252.3km |624.1km
     * 3 |156.5km |156km
     * 4 |39.1km |19.5km
     * 5 |4.9km |4.9km
     * 6 |1.2km |609.4m
     * 7 |152.9m |152.4m
     * 8 |38.2m| 19m
     * 9 |4.8m |4.8m
     * 10 |1.2m |59.5cm
     * 11 |14.9cm |14.9cm
     * 12 |3.7cm |1.9cm
     */
    @GetMapping("/nearby")
    public AjaxResult nearBySearch(SelectNearByParkRequest request) {
        return miniProgramBizService.getNearByParkInfoMysql(request);
    }

    /***
     * 保存小程序用户的车牌
     * @return
     */
    @PostMapping("/saveUserPlate")
    public AjaxResult saveUserPlate(@RequestBody SaveUserPlateRequest request) {
        boolean legalPlate = StringUtils.isLegalPlate(request.getPlate());
        if (!legalPlate) {
            return AjaxResult.error("车牌格式错误");
        }
        request.setUserId(SecurityUtils.getBaseUserId());
        return miniProgramBizService.saveUserPlate(request);
    }

    /***
     * 查找小程序用户的车牌
     * @return
     */
    @GetMapping("/selectUserPlate")
    public AjaxResult selectUserPlate() {
        Long baseUserId = SecurityUtils.getBaseUserId();
        return miniProgramBizService.selectUserPlate(baseUserId);
    }

    /***
     * 查找小程序用户的车牌
     * @return
     */
    @DeleteMapping("/deleteUserPlate")
    public AjaxResult deleteUserPlate(@RequestParam("plate") String plate) {
        Long baseUserId = SecurityUtils.getBaseUserId();
        return miniProgramBizService.deleteUserPlate(baseUserId, plate);
    }

    /**
     * 我的订单列表
     */
    @PostMapping(value = "/orderList")
    public AjaxResult orderList(@RequestBody OrderRequest orderRequest) {
        Long baseUserId = SecurityUtils.getBaseUserId();
        if (baseUserId == null) {
            return AjaxResult.error();
        }
        orderRequest.setBaseUserId(baseUserId);
        PageResult pageResult = miniProgramBizService.selectOrderList(orderRequest);
        return AjaxResult.success(pageResult);
    }

    /**
     * 订单详情
     */
    @GetMapping(value = "/orderDetail/{id}")
    public AjaxResult orderDetail(@PathVariable Long id) {
        ParkingOrderVo parkingOrderVo = miniProgramBizService.selectOrderDetailById(id);
        return AjaxResult.success(parkingOrderVo);
    }

    /**
     * @description: 开票
     * @author: HdongSun
     * @date: 2022/9/19 13:05
     * @param: [id]
     * @return: com.xique.common.core.web.domain.AjaxResult
     **/
    @GetMapping(value = "/invoice")
    public AjaxResult invoice(Long id) {
        return miniProgramBizService.invoice(id);
    }

    @GetMapping(value = "/getPushSetting")
    public AjaxResult getPushSetting() {
        Long userId = SecurityUtils.getBaseUserId();
        return miniProgramBizService.getPushSetting(userId);
    }

    @PostMapping(value = "/settingPush")
    public AjaxResult settingPush(Integer status) {
        Long userId = SecurityUtils.getBaseUserId();
        return miniProgramBizService.settingPush(userId, status);
    }
}
